﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Snowdreamist.Text.UBB;

namespace Snowdreamist.Test.Text.UBB
{
    [TestClass]
    public class NoGreedyUBBReaderTest
    {
        [TestMethod]
        public void TestPureText()
        {
            string ubbText = "This is a UBB text content\nLine2\nLine3";

            // generate expected doc
            UBBDocument expectedDoc = new UBBDocument();
            expectedDoc.Root.Add(new TextElement(ubbText));

            var reader = UBBReader.Create(UBBParseStrategy.NoGreedy);

            var doc = reader.Load(ubbText);

            Assert.AreEqual<bool>(true, expectedDoc.DocumentEquals(doc));
        }

        [TestMethod]
        public void TestSingleBoldText()
        {
            string ubbText = "Before bold[b]In bold[/b]After bold";

            // generate expected doc
            UBBDocument expectedDoc = new UBBDocument();
            expectedDoc.Root.AddRange(new IUBBElement[]{
                new TextElement("Before bold"),
                new BoldElement(new IUBBElement[]
                    {
                        new TextElement("In bold")
                    }),
                new TextElement("After bold")
            });

            var reader = UBBReader.Create(UBBParseStrategy.NoGreedy);

            var doc = reader.Load(ubbText);

            Assert.AreEqual<bool>(true, expectedDoc.DocumentEquals(doc));
        }

        [TestMethod]
        public void TestMultipleBoldText()
        {
            string[] ubbTexts = new string[] { "Before Bold", "In Bold", "Between Bold", "In Bold", "\tIn Bold", "After Bold" };
            string ubbText = string.Format("{0}[b]{1}[/b]{2}[b]{3}[b]{4}[/b][/b]{5}", ubbTexts[0], ubbTexts[1], ubbTexts[2], ubbTexts[3], ubbTexts[4], ubbTexts[5]);

            // generate expected doc
            UBBDocument expectedDoc = new UBBDocument();
            expectedDoc.Root.AddRange(new IUBBElement[]{
                new TextElement(ubbTexts[0]),
                new BoldElement(new IUBBElement[]{
                    new TextElement(ubbTexts[1])
                    }),
                new TextElement(ubbTexts[2]),
                new BoldElement(new IUBBElement[]{
                    new TextElement(ubbTexts[3]),
                    new BoldElement(new IUBBElement[]{
                        new TextElement(ubbTexts[4])
                    })
                }),
                new TextElement(ubbTexts[5])
            });

            var reader = UBBReader.Create(UBBParseStrategy.NoGreedy);
            var doc = reader.Load(ubbText);

            Assert.AreEqual<bool>(true, expectedDoc.DocumentEquals(doc));
        }

        [TestMethod]
        public void TestConfuseBoldText1()
        {
            string[] ubbTexts = new string[] { "Before bold", "[b]", "After bold" };
            string ubbText = string.Format("{0}[b]{1}[/b]{2}", ubbTexts[0], ubbTexts[1], ubbTexts[2]);

            // generate expected doc
            UBBDocument expectedDoc = new UBBDocument();
            expectedDoc.Root.AddRange(new IUBBElement[]{
                new TextElement(ubbTexts[0]),
                new BoldElement(new IUBBElement[]{
                    new TextElement(ubbTexts[1])
                }),
                new TextElement(ubbTexts[2])
            });

            var reader = UBBReader.Create(UBBParseStrategy.NoGreedy);
            var doc = reader.Load(ubbText);

            Assert.AreEqual<bool>(true, expectedDoc.DocumentEquals(doc));
        }

        [TestMethod]
        public void TestConfuseBoldText2()
        {
            string[] ubbTexts = new string[] { "Before bold", "In Bold", "[/b]" };
            string ubbText = string.Format("{0}[b]{1}[/b]{2}", ubbTexts[0], ubbTexts[1], ubbTexts[2]);

            // generate expected doc
            UBBDocument expectedDoc = new UBBDocument();
            expectedDoc.Root.AddRange(new IUBBElement[]{
                new TextElement(ubbTexts[0]),
                new BoldElement(new IUBBElement[]{
                    new TextElement(ubbTexts[1])
                }),
                new TextElement(ubbTexts[2])
            });

            var reader = UBBReader.Create(UBBParseStrategy.NoGreedy);
            var doc = reader.Load(ubbText);

            Assert.AreEqual<bool>(true, expectedDoc.DocumentEquals(doc));
        }

        [TestMethod]
        public void TestNotEqual1()
        {
            string ubbText = "Before bold[b]In bold[/b]After bold";

            // generate expected doc
            UBBDocument expectedDoc = new UBBDocument();
            expectedDoc.Root.AddRange(new IUBBElement[]{
                new TextElement("Before bold"),
                new BoldElement(new IUBBElement[]
                    {
                        new TextElement("In bold"),
                        new TextElement("Some error")
                    }),
                new TextElement("After bold")
            });

            var reader = UBBReader.Create(UBBParseStrategy.NoGreedy);

            var doc = reader.Load(ubbText);

            Assert.AreEqual<bool>(false, expectedDoc.DocumentEquals(doc));
        }

        [TestMethod]
        public void TestMixBoldItalicText()
        {
            string[] ubbTexts = new string[] { "Before Bold and Italic", "In Bold and Italic", "In Italic" };
            string ubbText = string.Format("{0}[b][i]{1}[/b]{2}[/i]", ubbTexts[0], ubbTexts[1], ubbTexts[2]);

            // generate expected doc
            UBBDocument expectedDoc = new UBBDocument();
            expectedDoc.Root.AddRange(new IUBBElement[]{
                new TextElement(ubbTexts[0]),
                new BoldElement(new IUBBElement[]{
                    new ItalicElement(new IUBBElement[]{
                        new TextElement(ubbTexts[1])
                    })
                }),
                new ItalicElement(new IUBBElement[]{
                    new TextElement(ubbTexts[2])
                })
            });

            var reader = UBBReader.Create(UBBParseStrategy.NoGreedy);
            var doc = reader.Load(ubbText);

            Assert.AreEqual<bool>(true, expectedDoc.DocumentEquals(doc));
        }

        [TestMethod]
        public void TestMixBasicLabels()
        {
            string[] ubbTexts = new string[] { "First", "In Bold", "Under", "Italic", "Strike", " Italic", "Code", "End" };
            string ubbText = string.Format("{0}[b]{1}[u]{2}[i]{3}[del]{4}[/del][/b][/u]{5}[/i][code]{6}[/code]{7}", ubbTexts);
            // generate expected doc
            UBBDocument expectedDoc = new UBBDocument();
            expectedDoc.Root.AddRange(new IUBBElement[]{
                new TextElement(ubbTexts[0]),
                new BoldElement(new IUBBElement[]{
                    new TextElement(ubbTexts[1]),
                    new UnderlineElement(new IUBBElement[]{
                        new TextElement(ubbTexts[2]),
                        new ItalicElement(new IUBBElement[]{
                            new TextElement(ubbTexts[3]),
                            new StrikethroughElement(new IUBBElement[]{
                                new TextElement(ubbTexts[4])
                            })
                        })
                    })
                }),
                new ItalicElement(new IUBBElement[]{
                    new TextElement(ubbTexts[5])
                }),
                new CodeElement(new IUBBElement[]{
                    new TextElement(ubbTexts[6])
                }),
                new TextElement(ubbTexts[7])
            });


            var reader = UBBReader.Create(UBBParseStrategy.NoGreedy);
            var doc = reader.Load(ubbText);

            Assert.AreEqual<bool>(true, expectedDoc.DocumentEquals(doc));
        }

        [TestMethod]
        public void TestMixAlignText()
        {
            string[] ubbTexts = new string[] { "left", "right", "center", "left", "leftcenter", "left", "right", "rightcenter", "right" };
            string ubbText = string.Format("[left]{0}[/left][right]{1}[/right][center]{2}[/center][align=left]{3}[center][b]{4}[/center]{5}[/b][/align][align=right]{6}[align=center]{7}[/align]{8}[/align]", ubbTexts);
            // generate expected doc
            UBBDocument expectedDoc = new UBBDocument();
            expectedDoc.Root.AddRange(new IUBBElement[] {
                new AlignElement(AlignType.Left, new IUBBElement[]{
                    new TextElement(ubbTexts[0])
                }),
                new AlignElement(AlignType.Right, new IUBBElement[]{
                    new TextElement(ubbTexts[1])
                }),
                new AlignElement(AlignType.Center, new IUBBElement[]{
                    new TextElement(ubbTexts[2])
                }),
                new AlignElement(AlignType.Left, new IUBBElement[]{
                    new TextElement(ubbTexts[3]),
                    new AlignElement(AlignType.Center, new IUBBElement[]{
                        new BoldElement(new IUBBElement[]{
                            new TextElement(ubbTexts[4])
                        })
                    }),
                    new BoldElement(new IUBBElement[]{
                        new TextElement(ubbTexts[5])
                    })
                }),
                new AlignElement(AlignType.Right, new IUBBElement[]{
                    new TextElement(ubbTexts[6]),
                    new AlignElement(AlignType.Center, new IUBBElement[]{
                        new TextElement(ubbTexts[7])
                    }),
                    new TextElement(ubbTexts[8])
                })
            });
            
            var reader = UBBReader.Create(UBBParseStrategy.NoGreedy);
            var doc = reader.Load(ubbText);

            string ubb = doc.ToString();
            System.Diagnostics.Debug.Write(ubb);

            Assert.AreEqual<bool>(true, expectedDoc.DocumentEquals(doc));
        }
    }
}
